<?php
/**
 * Table 
 * 
 * 具体表操作类
 *
 * @author   songhuan <iphper@yeah.net>
 * @version   $Id: Table.php 1 2010-08-10 14:40:00Z $
 */
abstract class Table
{	
	/**
	 * @var Adapter 对象
	 */
	protected $_adapter = null;
	
	/**
	 * @var int ID值
	 */
	protected $_id = null;
	
	/**
	 * @var array(
	 * 		'column' => array('value' => $default, 'updated' => false)
	 * )
	 */
	protected $_properties = array();
	
	/**
	 * @var string 表名
	 */
	protected $_table = null;
	
	/**
	 * @var string ID字段名
	 */
	protected $_idField = 'id';
	
	/**
	 * @var string 表前缀
	 */
	protected $_tblPrefix = null;
	
	public function __construct()
	{
		$this->_adapter = V::getAdapter();
		
		if (null === $this->_table)
			throw new Exception('table name can not null');
	}
	
	/**
	 * 查询一条记录
	 * 
	 * @param string|int|array $id 字段值
	 * @param string $field 字段名
	 * @return array 结果集
	 */
	public function load($id, $field = null)
	{
		if (!is_array($id)) 
		{
			if (null === $field) 
				$field = $this->_idField;
				
	        if ($field == $this->_idField) 
	        {
	            $id = (int) $id;
	            if ($id <= 0) 
	                return false;
	        }
	        
	        $id = array($field . ' = ?', $id);
		}
		$row = $this->getAdapter()->fields($this->getSelectFields())->where($id)->find();
		if ($row)
			$this->initProperties($row);
			
		return $row;
	}
	
	/**
	 * 插入或修改一条记录
	 */
	public function save()
    {	
        $isUpdate = ($this->getId() > 0);
        
        if ($isUpdate) 
        	$this->preUpdate();
        else 
        	$this->preInsert();	

        $row = array();
        foreach ($this->_properties as $k => $v) 
        {
        	if ($isUpdate && !$v['updated'])
            	continue;
            	
            $row[$k] = $v['value'];
        }
        
        if (count($row) > 0) 
        {
            if ($isUpdate) 
                $this->getAdapter()->fields($row)->where(array($this->_idField . ' = ?', $this->getId()))->update();
            else 
                $this->_id = $this->getAdapter()->fields($row)->insert();
        }
        
        if ($isUpdate) 
        	$this->postUpdate();
        else 
        	$this->postInsert();
    }
    
    /**
	 * 删除一条记录
	 */
	public function delete()
    {
        if ($this->getId() <= 0)
            return false;

        $this->preDelete();
        $rowCount = $this->getAdapter()->where(array($this->_idField . ' = ?', $this->getId()))->delete();
        $this->_id = null;
        $this->postDelete();
        return $rowCount;
    }
    
	/**
	 * 判读表中的某个字段值是否唯一
	 * 
	 * @param string $column 字段名
	 * @param string|int $value 字段值
	 * @return boolean
	 */
	public function unique($column, $value) 
	{
		$where = array($column . ' = ?', $value);
		return $this->totalResults($where) <= 0;
	}
	
	/**
	 * 总记录数
	 * 
	 * @param array $where array('username = ? AND password = ?', 'iphper', '123456')
	 * @return int
	 */
	public function totalResults($where = array())
	{
		return $this->getAdapter()->fields($this->_idField, '', 'COUNT')->where($where)->getColumnOne(0);
	}
	
    /**
	 * 将表中的数据组合成数组
	 * 
	 * @return array
	 */
    public function getRow()
    {
    	$row = array($this->_idField => $this->_id);
    	foreach ($this->_properties as $k => $v) 
            $row[$k] = $v['value'];
        
        return $row;
    }
    
    /**
     * 获取所有字段
     * 
     * @return array 查询字段
     */
    public function getSelectFields()
    {
	    $fields = array_keys($this->_properties);
	    array_unshift($fields, $this->_idField);
		
	    return $fields;
    }
	
	/**
	 * 获取数据库 Adapter 
	 * 
	 * @return Adapter 对象
	 */
	public function getAdapter()
	{
		return $this->_adapter->table($this->getTable(), '');
	}
    
	/**
     * 获取表名
     * 
     * @return string $table 表名
     */
    public function getTable()
    {	
		return $this->getTblPrefix() . $this->_table;
    }
    
    /**
     * @return 当前ID
     */
	public function getId()
	{
	    return (int) $this->_id;
	}
	
    /**
     * 设置ID值
     * 
     * @param string $id
     */
    public function setId($id)
    {
		$this->_id = (int) $id;
    }
    
    /**
     * 获取表前缀
     * 
     * @return string $tblPrefix
     */
    public function getTblPrefix()
    {
    	if (null === $this->_tblPrefix)
    		$this->setTblPrefix();
    	
    	return $this->_tblPrefix;
    }
    
    /**
     * 设置表前缀
     * 
     * @param string $tblPrefix
     */
    public function setTblPrefix($tblPrefix = null)
    {
		if (null !== $tblPrefix)
			$this->_tblPrefix = $tblPrefix;
		else if (isset(V::$config['db']['prefix']))
			$this->_tblPrefix = V::$config['db']['prefix'];
		
		return $this;
    }
    
	/**
	 * 初始化各字段默认值
	 * 
	 * @param array $row
	 * @return void
	 */
    public function initProperties($row, $updated = false)
    {
    	if (empty($row))
    		return false;
    	
        foreach ($this->_properties as $k => $v)
        {
        	if (array_key_exists($k, $row))
        	{
        		$this->_properties[$k]['value'] = $row[$k];
        		$this->_properties[$k]['updated'] = $updated;
        	}
        }
        if (array_key_exists($this->_idField, $row))
        	$this->_id = (int) $row[$this->_idField];
        
        return true;
    }
    
    /**
     * 向properties中添加一个数组
     * 
	 * @param array('field' => $default, 'column')
	 * @return void
	 */
	protected function _addProperties($properties = array())
	{
		foreach ($properties as $field => $default) 
		{
			if (is_numeric($field))
				$this->_addPropertie($default);
			else 
				$this->_addPropertie($field, $default);
		}
	}
	
    /**
     * 向properties中添加一个字段
     * 
     * @param string $field 字段名
     * @param string $default 默认值
     * @return void
     */
	protected function _addPropertie($field, $default = null)
    {
        $this->_properties[$field] = array('value' => $default, 'updated' => false);
    }
    
    public function __get($name)
    {
        return array_key_exists($name, $this->_properties) ? $this->_properties[$name]['value'] : null;
    }
    
    public function __set($name, $value)
    {
        if (array_key_exists($name, $this->_properties)) 
        {
        	$this->_properties[$name] = array('value' => $value, 'updated' => true);
            return true;
        }

        return false;
    }
    
    protected function preInsert()
    {
    }
    
    protected function postInsert()
    {
    }
    
    protected function preUpdate()
    {	
    }
    
    protected function postUpdate()
    {
    }
    
    protected function preDelete()
    {
    }
    
    protected function postDelete()
    {
    }
    
	/**
	 * @return 最后一次执行的SQL语句 - 测试用
	 */
	public function getSql()
	{
		return $this->_adapter->getSql();
	}
	
    /**
	 * @return 最后一次执行的Param参数 - 测试用
	 */
	public function getParams()
	{
		return $this->_adapter->getParams();
	}
}
